home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / os2 / octa209s.zip / octave-2.09 / src / utils.cc < prev    next >
C/C++ Source or Header  |  1997-07-10  |  11KB  |  551 lines

  1. /*
  2.  
  3. Copyright (C) 1996 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. /* Modified by Klaus Gebhardt, 1996 */
  24.  
  25. #ifdef HAVE_CONFIG_H
  26. #include <config.h>
  27. #endif
  28.  
  29. #include <climits>
  30. #include <csetjmp>
  31. #include <cstring>
  32.  
  33. #include <string>
  34.  
  35. #include <fstream.h>
  36. #include <iostream.h>
  37. #include <strstream.h>
  38.  
  39. #ifdef HAVE_UNISTD_H
  40. #ifdef HAVE_SYS_TYPES_H
  41. #include <sys/types.h>
  42. #endif
  43. #include <unistd.h>
  44. #endif
  45.  
  46. #if defined (HAVE_TERMIOS_H)
  47. #include <termios.h>
  48. #elif defined (HAVE_TERMIO_H)
  49. #include <termio.h>
  50. #elif defined (HAVE_SGTTY_H)
  51. #include <sgtty.h>
  52. #else
  53. LOSE! LOSE!
  54. #endif
  55.  
  56. #ifndef HAVE_STRNCASECMP
  57. extern "C" int strncasecmp (const char*, const char*, size_t);
  58. #endif
  59.  
  60. #include "SLStack.h"
  61.  
  62. #include "file-ops.h"
  63. #include "oct-cmplx.h"
  64. #include "str-vec.h"
  65.  
  66. #include <defaults.h>
  67. #include "defun.h"
  68. #include "dir-ops.h"
  69. #include "dirfns.h"
  70. #include "error.h"
  71. #include "gripes.h"
  72. #include "help.h"
  73. #include "input.h"
  74. #include "mappers.h"
  75. #include "oct-hist.h"
  76. #include "oct-obj.h"
  77. #include "pager.h"
  78. #include "pathsearch.h"
  79. #include "sysdep.h"
  80. #include "toplev.h"
  81. #include "unwind-prot.h"
  82. #include "utils.h"
  83. #include "variables.h"
  84.  
  85. // Top level context (?)
  86. extern jmp_buf toplevel;
  87.  
  88. // Save a string.
  89.  
  90. char *
  91. strsave (const char *s)
  92. {
  93.   if (! s)
  94.     return 0;
  95.  
  96.   int len = strlen (s);
  97.   char *tmp = new char [len+1];
  98.   tmp = strcpy (tmp, s);
  99.   return tmp;
  100. }
  101.  
  102. // Return to the main command loop in octave.cc.
  103.  
  104. extern "C" void
  105. jump_to_top_level (void)
  106. {
  107. #if ! defined (__EMX__) || ! defined (OS2)
  108.   run_all_unwind_protects ();
  109. #endif
  110.  
  111.   longjmp (toplevel, 1);
  112. }
  113.  
  114. int
  115. almost_match (const string& std, const string& s, int min_match_len,
  116.           int case_sens)
  117. {
  118.   int stdlen = std.length ();
  119.   int slen = s.length ();
  120.  
  121.   return (slen <= stdlen
  122.       && slen >= min_match_len
  123.       && (case_sens
  124.           ? (strncmp (std.c_str (), s.c_str (), slen) == 0)
  125.           : (strncasecmp (std.c_str (), s.c_str (), slen) == 0)));
  126. }
  127.  
  128. // Ugh.
  129.  
  130. int
  131. keyword_almost_match (const char **std, int *min_len, const string& s,
  132.               int min_toks_to_match, int max_toks)
  133. {
  134.   int status = 0;
  135.   int tok_count = 0;
  136.   int toks_matched = 0;
  137.  
  138.   if (s.empty () || max_toks < 1)
  139.     return status;
  140.  
  141.   char *kw = strsave (s.c_str ());
  142.  
  143.   char *t = kw;
  144.   while (*t != '\0')
  145.     {
  146.       if (*t == '\t')
  147.     *t = ' ';
  148.       t++;
  149.     }
  150.  
  151.   char *beg = kw;
  152.   while (*beg == ' ')
  153.     beg++;
  154.  
  155.   if (*beg == '\0')
  156.     return status;
  157.  
  158.  
  159.   char **to_match = new char * [max_toks + 1];
  160.   const char **s1 = std;
  161.   char **s2 = to_match;
  162.  
  163.   if (! s1 || ! s2)
  164.     goto done;
  165.  
  166.   s2[tok_count] = beg;
  167.   char *end;
  168.   while ((end = strchr (beg, ' ')) != 0)
  169.     {
  170.       *end = '\0';
  171.       beg = end + 1;
  172.  
  173.       while (*beg == ' ')
  174.     beg++;
  175.  
  176.       if (*beg == '\0')
  177.     break;
  178.  
  179.       tok_count++;
  180.       if (tok_count >= max_toks)
  181.     goto done;
  182.  
  183.       s2[tok_count] = beg;
  184.     }
  185.   s2[tok_count+1] = 0;
  186.  
  187.   s2 = to_match;
  188.  
  189.   for (;;)
  190.     {
  191.       if (! almost_match (*s1, *s2, min_len[toks_matched], 0))
  192.     goto done;
  193.  
  194.       toks_matched++;
  195.  
  196.       s1++;
  197.       s2++;
  198.  
  199.       if (! *s2)
  200.     {
  201.       status = (toks_matched >= min_toks_to_match);
  202.       goto done;
  203.     }
  204.  
  205.       if (! *s1)
  206.     goto done;
  207.     }
  208.  
  209.  done:
  210.  
  211.   delete [] kw;
  212.   delete [] to_match;
  213.  
  214.   return status;
  215. }
  216.  
  217. // Return non-zero if either NR or NC is zero.  Return -1 if this
  218. // should be considered fatal; return 1 if this is ok.
  219.  
  220. int
  221. empty_arg (const char *name, int nr, int nc)
  222. {
  223.   int is_empty = 0;
  224.  
  225.   if (nr == 0 || nc == 0)
  226.     {
  227.       int flag = Vpropagate_empty_matrices;
  228.  
  229.       if (flag < 0)
  230.     {
  231.       gripe_empty_arg (name, 0);
  232.       is_empty = 1;
  233.     }
  234.       else if (flag == 0)
  235.     {
  236.       gripe_empty_arg (name, 1);
  237.       is_empty = -1;
  238.     }
  239.       else
  240.     is_empty = 1;
  241.     }
  242.  
  243.   return is_empty;
  244. }
  245.  
  246. // See if the given file is in the path.
  247.  
  248. string
  249. search_path_for_file (const string& path, const string& name)
  250. {
  251.   dir_path p (path);
  252.  
  253.   return make_absolute (p.find (name), Vcurrent_directory);
  254. }
  255.  
  256. DEFUN (file_in_path, args, ,
  257.   "file_in_path (PATH, NAME)")
  258. {
  259.   octave_value_list retval;
  260.  
  261.   int argc = args.length () + 1;
  262.  
  263.   string_vector argv = args.make_argv ("file_in_path");
  264.  
  265.   if (error_state)
  266.     return retval;
  267.  
  268.   if (argc == 3)
  269.     {
  270.       string path = maybe_add_default_load_path (argv[1]);
  271.  
  272.       string fname = search_path_for_file (path, argv[2]);
  273.  
  274.       if (fname.empty ())
  275.     retval = Matrix ();
  276.       else
  277.     retval = fname;
  278.     }
  279.   else
  280.     print_usage ("file_in_path");
  281.  
  282.   return retval;
  283. }
  284.  
  285. string
  286. file_in_path (const string& name, const string& suffix)
  287. {
  288.   string nm = name;
  289.  
  290.   if (! suffix.empty ())
  291.     nm.append (suffix);
  292.  
  293.   if (Vcurrent_directory.empty ())
  294.     get_working_directory ("file_in_path");
  295.  
  296.   return search_path_for_file (Vload_path, nm);
  297. }
  298.  
  299. // See if there is an function file in the path.  If so, return the
  300. // full path to the file.
  301.  
  302. string
  303. fcn_file_in_path (const string& name)
  304. {
  305.   string retval;
  306.  
  307.   int len = name.length ();
  308.   
  309.   if (len > 0)
  310.     {
  311.       if (len > 2 && name [len - 2] == '.' && name [len - 1] == 'm')
  312.     retval = file_in_path (name, "");
  313.       else
  314.     retval = file_in_path (name, ".m");
  315.     }
  316.  
  317.   return retval;
  318. }
  319.  
  320. // See if there is an octave file in the path.  If so, return the
  321. // full path to the file.
  322.  
  323. string
  324. oct_file_in_path (const string& name)
  325. {
  326.   string retval;
  327.  
  328.   int len = name.length ();
  329.   
  330.   if (len > 0)
  331.     {
  332.       if (len > 2 && name [len - 4] == '.' && name [len - 3] == 'o'
  333.       && name [len - 2] == 'c' && name [len - 1] == 't')
  334.     retval = file_in_path (name, "");
  335.       else
  336.     retval = file_in_path (name, ".oct");
  337.     }
  338.  
  339.   return retval;
  340. }
  341.  
  342. const char *
  343. undo_string_escape (char c)
  344. {
  345.   if (! c)
  346.     return "";
  347.  
  348.   switch (c)
  349.     {
  350.     case '\a':
  351.       return "\\a";
  352.  
  353.     case '\b': // backspace
  354.       return "\\b";
  355.  
  356.     case '\f': // formfeed
  357.       return "\\f";
  358.  
  359.     case '\n': // newline
  360.       return "\\n";
  361.  
  362.     case '\r': // carriage return
  363.       return "\\r";
  364.  
  365.     case '\t': // horizontal tab
  366.       return "\\t";
  367.  
  368.     case '\v': // vertical tab
  369.       return "\\v";
  370.  
  371.     case '\\': // backslash
  372.       return "\\\\";
  373.  
  374.     case '"': // double quote
  375.       return "\\\"";
  376.  
  377.     default:
  378.       {
  379.     static char retval[2];
  380.     retval[0] = c;
  381.     retval[1] = '\0';
  382.     return retval;
  383.       }
  384.     }
  385. }
  386.  
  387. string
  388. undo_string_escapes (const string& s)
  389. {
  390.   string retval;
  391.  
  392.   for (size_t i = 0; i < s.length (); i++)
  393.     retval.append (undo_string_escape (s[i]));
  394.  
  395.   return retval;
  396. }
  397.  
  398. DEFUN (undo_string_escapes, args, ,
  399.   "undo_string_escapes (STRING)")
  400. {
  401.   octave_value retval;
  402.  
  403.   int nargin = args.length ();
  404.  
  405.   if (nargin == 1 && args(0).is_string ())
  406.     retval = undo_string_escapes (args(0).string_value ());
  407.   else
  408.     print_usage ("undo_string_escapes");
  409.  
  410.   return retval;
  411. }
  412.  
  413. // This function was adapted from xputenv from Karl Berry's kpathsearch
  414. // library.
  415.  
  416. void
  417. oct_putenv (const char *var_name, const char *value)
  418. {
  419.   static const char **saved_env_items = 0;
  420.   static unsigned saved_len;
  421.   char *old_item = 0;
  422.  
  423.   int new_len = strlen (var_name) + strlen (value) + 2;
  424.  
  425.   char *new_item = new char [new_len];
  426.  
  427.   sprintf (new_item, "%s=%s", var_name, value);
  428.  
  429. #ifndef SMART_PUTENV
  430.  
  431.   // Check if we have saved anything yet.
  432.  
  433.   if (! saved_env_items)
  434.     {
  435.       saved_env_items = new const char * [1];
  436.       saved_env_items[0] = var_name;
  437.       saved_len = 1;
  438.     }
  439.   else
  440.     {
  441.       // Check if we've assigned VAR_NAME before.
  442.  
  443.       unsigned len = strlen (var_name);
  444.  
  445.       for (unsigned i = 0; i < saved_len && ! old_item; i++)
  446.         {
  447.           if (strcmp (saved_env_items[i], var_name) == 0)
  448.             {
  449.               old_item = getenv (var_name);
  450.  
  451.               assert (old_item);
  452.  
  453.               // Back up to the `NAME=' in the environment before the
  454.           // value that getenv returns.
  455.  
  456.               old_item -= (len + 1);
  457.             }
  458.         }
  459.       
  460.       if (! old_item)
  461.         {
  462.           // If we haven't seen VAR_NAME before, save it.  Assume it
  463.       // is in safe storage.
  464.  
  465.           saved_len++;
  466.  
  467.       const char **tmp = new const char * [saved_len];
  468.  
  469.       for (unsigned i = 0; i < saved_len - 1; i++)
  470.         tmp[i] = saved_env_items[i];
  471.  
  472.       tmp[saved_len - 1] = var_name;
  473.  
  474.           delete [] saved_env_items;
  475.  
  476.       saved_env_items = tmp;
  477.         }
  478.     }
  479.  
  480. #endif
  481.  
  482.   // As far as I can see there's no way to distinguish between the
  483.   // various errors; putenv doesn't have errno values.
  484.  
  485.   if (putenv (new_item) < 0)
  486.     error ("putenv (%s) failed", new_item);
  487.   
  488. #ifndef SMART_PUTENV
  489.  
  490.   // Can't free `new_item' because its contained value is now in
  491.   // `environ', but we can free `old_item', since it's been replaced.
  492.  
  493.   delete [] old_item;
  494.  
  495. #endif
  496. }
  497.  
  498. static void
  499. warn_old_style_preference (bool val, const string& sval)
  500. {
  501.   warning
  502.     ("preference of \"%s\" is obsolete -- use numeric value of %d instead",
  503.      sval.c_str (), (val ? 1 : 0));
  504. }
  505.  
  506. // Check the value of a string variable to see if it it's ok to do
  507. // something.
  508. //
  509. //   return of  1 => always ok.
  510. //   return of  0 => never ok.
  511. //   return of -1 => ok, but give me warning (default).
  512.  
  513. int
  514. check_preference (const string& var)
  515. {
  516.   int pref = -1;
  517.  
  518.   string val = builtin_string_variable (var);
  519.  
  520.   if (val.empty ())
  521.     {
  522.       double dval = 0;
  523.       if (builtin_real_scalar_variable (var, dval))
  524.     pref = NINT (dval);
  525.     }
  526.   else
  527.     {
  528.       if (val.compare ("yes", 0, 3) == 0
  529.       || val.compare ("true", 0, 4) == 0)
  530.     {
  531.       warn_old_style_preference (true, val);
  532.       pref = 1;
  533.     }
  534.       else if (val.compare ("never", 0, 5) == 0
  535.            || val.compare ("no", 0, 2) == 0
  536.            || val.compare ("false", 0, 5) == 0)
  537.     {
  538.       warn_old_style_preference (false, val);
  539.       pref = 0;
  540.     }
  541.     }
  542.  
  543.   return pref;
  544. }
  545.  
  546. /*
  547. ;;; Local Variables: ***
  548. ;;; mode: C++ ***
  549. ;;; End: ***
  550. */
  551.